package com.xju.atpgs.generator;

import com.xju.atpgs.entity.Question;

import java.util.*;

public class Paper {
    private double adaptationDegree;
    private double difficulty;
    private List<Integer> choice;
    private List<Integer> judge;
    private List<Integer> filling;
    private List<Integer> shortAnswer;
    private List<Integer> solve;
    private List<Integer> questionList;
    private GeneticParameter geneticParameter;

    public GeneticParameter getGeneticParameter() {
        return geneticParameter;
    }

    public void setGeneticParameter(GeneticParameter geneticParameter) {
        this.geneticParameter = geneticParameter;
    }

    public Paper(GeneticParameter geneticParameter) {
        this.geneticParameter=geneticParameter;
        questionList=new ArrayList<>();
        for(int i=0;i<geneticParameter.getTotalNumber();i++){
            questionList.add(null);
        }
        updateQuestions();
    }

    public Paper(double adaptationDegree, double difficulty, List<Integer> choice, List<Integer> judge, List<Integer> filling, List<Integer> shortAnswer, List<Integer> solve,GeneticParameter geneticParameter) {
        this.adaptationDegree = adaptationDegree;
        this.difficulty = difficulty;
        this.choice = choice;
        this.judge = judge;
        this.filling = filling;
        this.shortAnswer = shortAnswer;
        this.solve = solve;
        upadteQuestionList();
        this.geneticParameter=geneticParameter;
    }

    public double getDifficulty() {
        return difficulty;
    }


    public double getAdaptationDegree() {
        return adaptationDegree;
    }

    public void setAdaptationDegree(double adaptationDegree) {
        this.adaptationDegree = adaptationDegree;
    }

    public void setDifficulty(double difficulty) {
        this.difficulty = difficulty;
    }

    public List<Integer> getChoice() {
        return choice;
    }

    public void setChoice(List<Integer> choice) {
        this.choice = choice;
    }

    public List<Integer> getJudge() {
        return judge;
    }

    public void setJudge(List<Integer> judge) {
        this.judge = judge;
    }

    public List<Integer> getFilling() {
        return filling;
    }

    public void setFilling(List<Integer> filling) {
        this.filling = filling;
    }

    public List<Integer> getShortAnswer() {
        return shortAnswer;
    }

    public void setShortAnswer(List<Integer> shortAnswer) {
        this.shortAnswer = shortAnswer;
    }

    public List<Integer> getSolve() {
        return solve;
    }

    public void setSolve(List<Integer> solve) {
        this.solve = solve;
    }

    public List<Integer> getQuestionList() {
        return questionList;
    }

    public void setQuestionList(List<Integer> questionList) {
        this.questionList = questionList;
    }

    public void upadteQuestionList(){
        List<Integer> questionList=new ArrayList<>();
        questionList.addAll(this.choice);
        questionList.addAll(this.judge);
        questionList.addAll(this.filling);
        questionList.addAll(this.shortAnswer);
        questionList.addAll(this.solve);
        this.questionList=questionList;
    }

    public void updateQuestions(){
        this.choice=this.questionList.subList(0,geneticParameter.getChoiceNum());
        this.judge=this.questionList.subList(geneticParameter.getChoiceNum(),geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum());
        this.filling=this.questionList.subList(geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum(),geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum()+geneticParameter.getFillingNum());
        this.shortAnswer=this.questionList.subList(geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum()+geneticParameter.getFillingNum(),geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum()+geneticParameter.getFillingNum()+geneticParameter.getShortAnswerNum());
        this.solve=this.questionList.subList(geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum()+geneticParameter.getFillingNum()+geneticParameter.getShortAnswerNum(),geneticParameter.getChoiceNum()+geneticParameter.getJudgeNum()+geneticParameter.getFillingNum()+geneticParameter.getShortAnswerNum()+geneticParameter.getSolveNum());
    }
    public void saveQuestion(int index, Integer question){
        this.questionList.set(index,question);
        updateQuestions();
    }

    public void updateParameter(){
        double difficulty=0;
        for (Integer index:choice){
            String d=geneticParameter.getChoiceQuestion().get(index).getQuesLevel();
            difficulty+=Double.parseDouble(d)*geneticParameter.getChoiceScore();
        }
        for (Integer index:judge){
            String d=geneticParameter.getJudgeQuestion().get(index).getQuesLevel();
            difficulty+=Double.parseDouble(geneticParameter.getJudgeQuestion().get(index).getQuesLevel())*geneticParameter.getJudgeScore();
        }
        for (Integer index:filling){
            String d=geneticParameter.getFillingQuestion().get(index).getQuesLevel();
            difficulty+=Double.parseDouble(geneticParameter.getFillingQuestion().get(index).getQuesLevel())*geneticParameter.getChoiceScore();
        }
        for (Integer index:shortAnswer){
            String d=geneticParameter.getShortAnswerQuestion().get(index).getQuesLevel();
            difficulty+=Double.parseDouble(geneticParameter.getShortAnswerQuestion().get(index).getQuesLevel())*geneticParameter.getShortAnswerScore();
        }
        for (Integer index:solve){
            String d=geneticParameter.getSolveQuestion().get(index).getQuesLevel();
            difficulty+=Double.parseDouble(geneticParameter.getSolveQuestion().get(index).getQuesLevel())*geneticParameter.getSolveScore();
        }
        this.difficulty=difficulty/geneticParameter.getTotalScore();
        this.adaptationDegree=1-Math.abs(geneticParameter.getEXPECT()-this.difficulty);
    }

    public void updateRepeat(){
        Random random=new Random();

        HashSet<Integer> newChoice=new HashSet<>(choice);
        HashSet<Integer> newJudge=new HashSet<>(judge);
        HashSet<Integer> newFilling=new HashSet<>(filling);
        HashSet<Integer> newShortAnswer=new HashSet<>(shortAnswer);
        HashSet<Integer> newSolve=new HashSet<>(solve);
        for (Integer each:choice){
            int g=choice.indexOf(each);
            choice.set(g,-1);
        }
        for (Integer each:judge){
            int g=judge.indexOf(each);
            judge.set(g,-1);
        }
        for (Integer each:filling){
            int g=filling.indexOf(each);
            filling.set(g,-1);
        }
        for (Integer each:shortAnswer){
            int g=shortAnswer.indexOf(each);
            shortAnswer.set(g,-1);
        }
        for (Integer each:solve){
            int g=solve.indexOf(each);
            solve.set(g,-1);
        }

        Iterator it=newChoice.iterator();
        int k=0;
        while (it.hasNext()){
            choice.set(k,(Integer)it.next());
            k++;
        }
        int i=k;
        while (i<geneticParameter.getChoiceNum()){
            int j=random.nextInt(geneticParameter.getChoiceQuestion().size());
            if(!choice.contains(j)){
                choice.set(i,j);
                i++;
            }
        }

        it=newJudge.iterator();
        k=0;
        while (it.hasNext()){
            judge.set(k,(Integer)it.next());
            k++;
        }
        i=k;
        while (i<geneticParameter.getJudgeNum()){
            int j=random.nextInt(geneticParameter.getJudgeQuestion().size());
            if(!judge.contains(j)){
                judge.set(i,j);
                i++;
            }
        }

        it=newFilling.iterator();
        k=0;
        while (it.hasNext()){
            filling.set(k,(Integer)it.next());
            k++;
        }
        i=k;
        while (i<geneticParameter.getFillingNum()){
            int j=random.nextInt(geneticParameter.getFillingQuestion().size());
            if(!filling.contains(j)){
                filling.set(i,j);
                i++;
            }
        }

        it=newShortAnswer.iterator();
        k=0;
        while (it.hasNext()){
            shortAnswer.set(k,(Integer)it.next());
            k++;
        }
        i=k;
        while (i<geneticParameter.getShortAnswerNum()){
            int j=random.nextInt(geneticParameter.getShortAnswerQuestion().size());
            if(!shortAnswer.contains(j)){
                shortAnswer.set(i,j);
                i++;
            }
        }

        it=newSolve.iterator();
        k=0;
        while (it.hasNext()){
            solve.set(k,(Integer)it.next());
            k++;
        }
        i=k;
        while (i<geneticParameter.getSolveNum()){
            int j=random.nextInt(geneticParameter.getSolveQuestion().size());
            if(!solve.contains(j)){
                solve.set(i,j);
                i++;
            }
        }

    }

    public List<Question> getChoiceQuestion(){
        List<Question> questionList=new ArrayList<>();
        for (Integer index:choice){
            Question question=geneticParameter.getChoiceQuestion().get(index);
            questionList.add(question);
        }
        return questionList;
    }

    public List<Question> getFillingQuestion(){
        List<Question> questionList=new ArrayList<>();
        for (Integer index:filling){
            Question question=geneticParameter.getFillingQuestion().get(index);
            questionList.add(question);
        }
        return questionList;
    }

    public List<Question> getJudgeQuestion(){
        List<Question> questionList=new ArrayList<>();
        for (Integer index:judge){
            Question question=geneticParameter.getJudgeQuestion().get(index);
            questionList.add(question);
        }
        return questionList;
    }

    public List<Question> getShortAnswerQuestion(){
        List<Question> questionList=new ArrayList<>();
        for (Integer index:shortAnswer){
            Question question=geneticParameter.getShortAnswerQuestion().get(index);
            questionList.add(question);
        }
        return questionList;
    }

    public List<Question> getSolveQuestion(){
        List<Question> questionList=new ArrayList<>();
        for (Integer index:solve){
            Question question=geneticParameter.getSolveQuestion().get(index);
            questionList.add(question);
        }
        return questionList;
    }
}
